/**
 * Juice
 * com.juice.orange.game.util
 * OutputMessage.java
 */
package com.hh.game.service.gateway.codec.websocket;

import com.alibaba.fastjson.JSON;
import com.hh.game.service.gateway.manager.MessageConstant;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.util.ReferenceCounted;


/**
 * ------------------------------------------------
 * | short | string | int | string | string | short|
 * ------------------------------------------------
 * | 2000 | version| len | route | data json| 1000|
 * ------------------------------------------------
 */
public class OutputMessage {
    private ByteBuf byteBuf;
    private String route;
    private Object result;

    public OutputMessage(String route, Object data) {
        this(MessageConstant.VERSION_DEFAULT, route, null, data);
    }

    public OutputMessage(String route, MessageDataType dataType, Object data) {
        this(MessageConstant.VERSION_DEFAULT, route, dataType, data);
    }

    public OutputMessage(String version, String route, Object data) {
        this(version, route, null, data);
    }

    public OutputMessage(String version, String route, MessageDataType dataType, Object data) {
        this.route = route;
        this.result = data;

        this.byteBuf = PooledByteBufAllocator.DEFAULT.buffer();
//        byteBuf.retain();

        byteBuf.writeShort(MessageConstant.HEAD);

        byte[] versionBytes = version.getBytes();
        byteBuf.writeInt(versionBytes.length);
        byteBuf.writeBytes(versionBytes);

        byte[] routeBytes = route.getBytes();

        byte[] dataBytes;
        byte type;
        if (data == null) {
            type = MessageDataType.JSON.getType();
            dataBytes = new byte[0];
        } else if (data instanceof byte[]) {
            type = MessageDataType.BYTE.getType();
            dataBytes = (byte[]) data;
        } else if (data instanceof String) {
            type = MessageDataType.STRING.getType();
            dataBytes = data.toString().getBytes();
        } else {
            type = MessageDataType.JSON.getType();
            dataBytes = JSON.toJSONString(data).getBytes();
        }

        int len = routeBytes.length + dataBytes.length + 4 * 2;
        byteBuf.writeInt(len);

        byteBuf.writeInt(routeBytes.length);
        byteBuf.writeBytes(routeBytes);

        int dataBytesLen = dataBytes.length;
        if (dataType != null) {
            type = dataType.getType();
            dataBytesLen = -1;
        }
        byteBuf.writeByte(type);
        byteBuf.writeInt(dataBytesLen);
        if (dataBytes.length > 0) {
            byteBuf.writeBytes(dataBytes);
        }

        byteBuf.writeShort(MessageConstant.TAIL);
    }

    public ByteBuf getByteBuf() {
        return byteBuf;
    }

    public Object getResult() {
        return result;
    }

    public String getRoute() {
        return route;
    }

    @Override
    public String toString() {
        byteBuf.markReaderIndex();
        InputMessage in = InputMessage.buildInputMessage(byteBuf);
        byteBuf.resetReaderIndex();
        return in.toString();
    }

    public boolean release() {
        return byteBuf.release();
    }

    public boolean release(int i) {
        return byteBuf.release(i);
    }
}
